package com.rslai.base.tool.servertest.command;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.rslai.base.tool.servertest.context.Context;
import com.rslai.base.tool.servertest.database.SqlRunner;
import com.rslai.base.tool.servertest.exception.ExecuteException;
import com.rslai.base.tool.servertest.model.KeyValueStore;
import com.rslai.base.tool.servertest.response.Response;
import com.rslai.base.tool.servertest.util.CloneUtil;
import com.rslai.base.tool.servertest.util.KeyValueUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;

public class SqlStepCommand extends ParameterizedCommand {
    public SqlStepCommand(List<KeyValueStore> params) {
        super(params);
    }

    protected Response doExecuteInternal(Response preResult, List<KeyValueStore> processedParams, Context context) throws Throwable {
        String sql = getSql(processedParams);
        String database = getDatabase(processedParams);
        try {
            this.logger.info("sql command<sql={}> is starting...", sql);
            SqlRunner sqlRunner = getDbUtil(database);
            List query = sqlRunner.execute(sql);
            String resultJson = getExpectJson(query);
            return new Response(resultJson, null);
        } catch (Exception e) {
            String message = String.format("sql step command invoke error,sql=<%s>", new Object[]{sql});
            this.logger.error(message, e);
            throw new ExecuteException(message, e);
        }
    }

    private String getSql(List<KeyValueStore> processedParams) {
        return KeyValueUtil.getValueByKey("sql", processedParams);
    }

    private String getDatabase(List<KeyValueStore> processedParams) {
        return KeyValueUtil.getValueByKey("database", processedParams);
    }

    public StepCommand doClone() {
        return new SqlStepCommand(CloneUtil.cloneKeyValueStore(this.params));
    }

    protected SqlRunner getDbUtil(String database) {
        return new SqlRunner(database);
    }

    private String getExpectJson(List<Map<String, Object>> query) {
        if ((query == null) || (query.size() == 0))
            return JSON.toJSONString(null);
        String expectJson;
        if (query.size() == 1)
            expectJson = JSON.toJSONString(query.get(0), new SerializerFeature[]{SerializerFeature.WriteMapNullValue});
        else {
            expectJson = JSON.toJSONString(query, new SerializerFeature[]{SerializerFeature.WriteMapNullValue});
        }
        return expectJson;
    }

    public Map<String, Object> toReport() {
        Map details = new HashMap();
        details.put("stepName", String.format("在数据库 %s 上执行:", new Object[]{getDatabase(this.params)}));
        details.put("name", String.format("SQL: %s", new Object[]{getSql(this.params)}));
        List params = new ArrayList();
        details.put("params", params);
        return details;
    }
}
